﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;

namespace Clarendon.AzureBilling.Library
{
    /// <summary>
    /// Class used to get the service properties of an individual service when requested
    /// </summary>
    public class ServicePropertiesRequester : RequestAzureService
    {
        /// <summary>
        /// An event which the client will subscribe to to return the hosted service list from the Azure subscription
        /// </summary>
        public event AzureHostedServiceEventHandler AzureHostedServiceListReturned;
        /// <summary>
        /// Keeps a count of the updates to the collection class
        /// </summary>
        private int _count = 0;
        /// <summary>
        /// Default constructor for the ServicePropertiesRequester class
        /// </summary>
        public ServicePropertiesRequester(ServiceManager manager) : base(manager)
        {
            Parser = new XmlParseServiceProperties();
        }

        /// <summary>
        /// Populate used to parse the XML return from Azure
        /// </summary>
        public override void Populate(HttpWebResponse response)
        {
            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                lock (this)
                {
                    int count = 0;
                    HostedService service = Parser.ParseXmlString<HostedService>(reader.ReadToEnd());
                    // update the item in the collection with an alternative that contains the service properties
                    // TODO: Run some tests on the output to determine whether <Deployments>/<Deployment> is a one-to-one mapping
                    Trace.WriteLine(String.Format("Azure returned services name: {0},  for subscription id {1}", service.Name, Manager.SubscriptionId));
                    Manager.HostedServices.Where(a => a.Name == service.Name)
                                          .ToList()
                                          .ForEach(a => { a.AffinityGroup = service.AffinityGroup; a.Location = service.Location;
                                                          a.Description = service.Description; 
                                                          a.Deployments = new List<Deployment>();
                                                          a.Deployments.Add(new Deployment(service.Deployments[count++].Name));});
                    List<HostedService> hostedServices = Manager.HostedServices;    
                    // release the semaphore and fire the event to let clients know that the services have been populated
                    if (++_count >= Manager.HostedServices.Count && Manager.Semaphore != null)
                    {
                        Trace.WriteLine(String.Format("Finished getting hosted service information for subscription id {0}", Manager.SubscriptionId));
                        Manager.HostedServices = hostedServices;
                        ReleaseSemaphore();
                    }   
                }
            }
        }

        /// <summary>
        /// Gets the properties of each service that is hosted in the subscription
        /// </summary>
        public override void MakeServiceRequest()
        {
            var services = Manager.HostedServices;
            // we want to throw an exception if the hosted services list has not been downloaded yet
            if (services == null)
                throw new AzureServicesException(
                    "unable to get service information - use the ServiceRequester before using the ServicePropertiesRequester");
            // iterate through the services to fire off the async requests
            foreach (var service in services)
            {
                ServiceManagementRequest serviceManager = GetServiceManagementRequest("hostedservices/" + service.Name + "?embed-detail=true");
                QueryManager.MakeASyncRequest(serviceManager, Manager.CertificateFile, 
                    new ServiceManager.AsyncResponseParser(Populate));
                //Interlocked.Increment(ref _count);
            }
        }
    }
}
